home *** CD-ROM | disk | FTP | other *** search
- #!/bin/sh
-
- STATEDIR=/var/lib/initramfs-tools
- BOOTDIR=/boot
- CONF=/etc/initramfs-tools/update-initramfs.conf
- KPKGCONF=/etc/kernel-img.conf
- USETRIGGERS=true
- mode=""
- version=""
-
- set -e
-
- [ -r ${CONF} ] && . ${CONF}
-
- if $USETRIGGERS \
- && [ x"$DPKG_MAINTSCRIPT_PACKAGE" != x ] \
- && [ $# = 1 ] \
- && [ x"$1" = x-u ] \
- && dpkg-trigger --check-supported 2>/dev/null
- then
- if dpkg-trigger --no-await update-initramfs; then
- echo "update-initramfs: deferring update (trigger activated)"
- exit 0
- fi
- fi
-
- usage()
- {
- if [ -n "${1}" ]; then
- printf "${@}\n\n" >&2
- fi
- cat >&2 << EOF
- Usage: ${0} [OPTION]...
-
- Options:
- -k [version] Specify kernel version or 'all'
- -c Create a new initramfs
- -u Update an existing initramfs
- -d Remove an existing initramfs
- -t Take over a custom initramfs with this one
- -b Set alternate boot directory
- -v Be verbose
- -h This message
-
- EOF
- exit 1
- }
-
- # chroot check
- chrooted()
- {
- # borrowed from udev's postinst
- if [ "$(stat -c %d/%i /)" = "$(stat -Lc %d/%i /proc/1/root 2>/dev/null)" ]; then
- # the devicenumber/inode pair of / is the same as that of
- # /sbin/init's root, so we're *not* in a chroot and hence
- # return false.
- return 1
- fi
- return 0
- }
-
- mild_panic()
- {
- if [ -n "${1}" ]; then
- printf "${@}\n" >&2
- fi
- exit 0
- }
-
- panic()
- {
- if [ -n "${1}" ]; then
- printf "${@}\n" >&2
- fi
- exit 1
- }
-
- verbose()
- {
- if [ "${verbose}" = 1 ]; then
- printf "${@}\n"
- fi
- }
-
- version_exists()
- {
- [ -e "${STATEDIR}/${1}" ] && [ -e "${initramfs}" ]
- return $?
- }
-
- set_initramfs()
- {
- initramfs="${BOOTDIR}/initrd.img-${version}"
- }
-
-
- # backup initramfs while running
- backup_initramfs()
- {
- [ ! -r "${initramfs}" ] && return 0
- initramfs_bak="${initramfs}.dpkg-bak"
- [ -r "${initramfs_bak}" ] && rm -f "${initramfs_bak}"
- ln -f "${initramfs}" "${initramfs_bak}" \
- || cp -a "${initramfs}" "${initramfs_bak}"
- verbose "Keeping ${initramfs_bak}"
- }
-
- # keep booted initramfs
- backup_booted_initramfs()
- {
- initramfs_bak="${initramfs}.dpkg-bak"
-
- # first time run thus no backup
- [ ! -r "${initramfs_bak}" ] && return 0
-
- # chroot with no /proc
- [ ! -r /proc/uptime ] && rm -f "${initramfs_bak}" && return 0
-
- # no kept backup wanted
- [ "${backup_initramfs}" = "no" ] && rm -f "${initramfs_bak}" && return 0
-
- # no backup yet
- if [ ! -r "${initramfs}.bak" ]; then
- mv -f ${initramfs_bak} "${initramfs}.bak"
- verbose "Backup ${initramfs}.bak"
- return 0
- fi
-
- # keep booted initramfs
- uptime_days=$(awk '{printf "%d", $1 / 3600 / 24}' /proc/uptime)
- if [ -n "$uptime_days" ]; then
- boot_initramfs=$(find "${initramfs}.bak" -mtime +${uptime_days})
- fi
- if [ -n "${boot_initramfs}" ]; then
- mv -f "${initramfs_bak}" "${initramfs}.bak"
- verbose "Backup ${initramfs}.bak"
- return 0
- fi
- verbose "Removing current backup ${initramfs_bak}"
- rm -f ${initramfs_bak}
- }
-
- # nuke generated copy
- remove_initramfs()
- {
- [ -z "${initramfs_bak}" ] && return 0
- rm -f "${initramfs_bak}"
- verbose "Removing ${initramfs_bak}"
- }
-
-
- generate_initramfs()
- {
- echo "update-initramfs: Generating ${initramfs}"
- OPTS="-o"
- if [ "${verbose}" = 1 ]; then
- OPTS="-v ${OPTS}"
- fi
- if mkinitramfs ${OPTS} "${initramfs}.new" "${version}"; then
- mv -f "${initramfs}.new" "${initramfs}"
- set_sha1
- else
- mkinitramfs_return="$?"
- remove_initramfs
- rm -f "${initramfs}.new"
- if [ "$mkinitramfs_return" = "2" ]; then
- # minversion wasn't met, exit 0
- exit 0
- fi
- echo "update-initramfs: failed for ${initramfs}"
- exit $mkinitramfs_return
- fi
- }
-
- # lilo call
- run_lilo()
- {
- # show lilo errors on failure
- if ! lilo -t > /dev/null 2>&1 ; then
- echo "ERROR lilo fails for new ${initramfs}:"
- echo
- lilo -t
- fi
- lilo
- }
-
- # check if lilo is on mbr
- mbr_check()
- {
- # try to discover grub and be happy
- # FIXME: check grub2 /boot/grub/grub.cfg
- [ -r /boot/grub/menu.lst ] \
- && groot=$(awk '/^root/{print substr($2, 2, 3); exit}' \
- /boot/grub/menu.lst)
- [ -e /boot/grub/device.map ] && [ -n "${groot}" ] \
- && dev=$(awk "/${groot}/{ print \$NF}" /boot/grub/device.map)
- [ -n "${dev}" ] && [ -r ${dev} ] \
- && dd if="${dev}" bs=512 skip=0 count=1 2> /dev/null \
- | grep -q GRUB && return 0
-
- # check out lilo.conf for validity
- boot=$(awk -F = '/^boot=/{ print $2}' /etc/lilo.conf)
- [ -z "${boot}" ] && return 0
- case ${boot} in
- /dev/md/*)
- if [ -r /proc/mdstat ]; then
- MD=${boot#/dev/md/}
- boot="/dev/$(awk "/^md${MD}/{print substr(\$5, 1, 3)}" \
- /proc/mdstat)"
- fi
- ;;
- /dev/md*)
- if [ -r /proc/mdstat ]; then
- MD=${boot#/dev/}
- boot="/dev/$(awk "/^${MD}/{print substr(\$5, 1, 3)}" \
- /proc/mdstat)"
- fi
- ;;
- esac
- [ ! -r "${boot}" ] && return 0
- dd if="${boot}" bs=512 skip=0 count=1 2> /dev/null | grep -q LILO \
- && run_lilo && return 0
-
- # no idea which bootloader is used
- echo
- echo "WARNING: grub and lilo installed."
- echo "If you use grub as bootloader everything is fine."
- echo "If you use lilo as bootloader you must run lilo!"
- echo
- }
-
- # Invoke bootloader
- run_bootloader()
- {
- # if both lilo and grub around, figure out if lilo needs to be run
- if [ -x "$(command -v update-grub)" ] || [ -e /boot/grub/menu.lst ] \
- || [ -e /boot/grub/grub.cfg ]; then
- if [ -e /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
- [ -r "${KPKGCONF}" ] && \
- do_b=$(awk '/^do_bootloader/{print $3}' "${KPKGCONF}")
- if [ "${do_b}" = "yes" ] || [ "${do_b}" = "Yes" ] \
- || [ "${do_b}" = "YES" ]; then
- run_lilo
- return 0
- elif [ "${do_b}" = "no" ] || [ "${do_b}" = "No" ] \
- || [ "${do_b}" = "NO" ]; then
- return 0
- else
- mbr_check
- return 0
- fi
- fi
- return 0
- fi
- if [ -r /etc/lilo.conf ] && [ -x /sbin/lilo ]; then
- run_lilo
- return 0
- fi
- if [ -x /sbin/elilo ]; then
- elilo
- return 0
- fi
- if [ -r /etc/zipl.conf ]; then
- zipl
- fi
- if [ -r /etc/kernel-img.conf ] && grep -q '^postinst_hook[[:space:]]*=[[:space:]]*[^[:space:]]' /etc/kernel-img.conf; then
- if flash-kernel --supported >/dev/null 2>&1; then
- flash-kernel
- fi
- fi
- }
-
- compare_sha1()
- {
- sha1sum "${initramfs}" | diff "${STATEDIR}/${version}" - >/dev/null 2>&1
- return $?
- }
-
- # Note that this must overwrite so that updates work.
- set_sha1()
- {
- sha1sum "${initramfs}" > "${STATEDIR}/${version}"
- }
-
- delete_sha1()
- {
- rm -f "${STATEDIR}/${version}"
- }
-
- # ro /boot is not modified
- ro_boot_check()
- {
- # check irrelevant inside of a chroot
- if [ ! -r /proc/mounts ] || chrooted; then
- return 0
- fi
-
- boot_opts=$(awk '/boot/{if ((match($4, /^ro/) || match($4, /,ro/)) \
- && $2 == "/boot") print "ro"}' /proc/mounts)
- if [ -n "${boot_opts}" ]; then
- echo "WARNING: /boot is ro mounted."
- echo "update-initramfs: Not updating ${initramfs}"
- exit 0
- fi
- }
-
- get_sorted_versions()
- {
- version_list=""
-
- for gsv_x in "${STATEDIR}"/*; do
- gsv_x="$(basename "${gsv_x}")"
- if [ "${gsv_x}" = '*' ]; then
- return 0
- fi
- worklist=""
- for gsv_i in $version_list; do
- if dpkg --compare-versions "${gsv_x}" '>' "${gsv_i}"; then
- worklist="${worklist} ${gsv_x} ${gsv_i}"
- gsv_x=""
- else
- worklist="${worklist} ${gsv_i}"
- fi
- done
- if [ "${gsv_x}" != "" ]; then
- worklist="${worklist} ${gsv_x}"
- fi
- version_list="${worklist}"
- done
-
- verbose "Available versions: ${version_list}"
- }
-
- set_current_version()
- {
- if [ -f /boot/initrd.img-`uname -r` ]; then
- version=`uname -r`
- fi
- }
-
- set_linked_version()
- {
- if [ -L /initrd.img -a -e /initrd.img ]; then
- linktarget="$(basename "$(readlink /initrd.img)")"
- fi
-
- if [ -L /boot/initrd.img -a -e /boot/initrd.img ]; then
- linktarget="$(basename "$(readlink /boot/initrd.img)")"
- fi
-
- if [ -z "${linktarget}" ]; then
- return
- fi
-
- version="${linktarget##initrd.img-}"
- }
-
- set_highest_version()
- {
- get_sorted_versions
- set -- ${version_list}
- version=${1}
- }
-
- create()
- {
- if [ -z "${version}" ]; then
- usage "Create mode requires a version argument"
- fi
-
- set_initramfs
-
- if [ "${takeover}" = 0 ]; then
- if version_exists "${version}"; then
- panic "Cannot create version ${version}: already exists"
- fi
-
- if [ -e "${initramfs}" ]; then
- panic "${initramfs} already exists, cannot create."
- fi
- fi
-
- generate_initramfs
- }
-
- update()
- {
- if [ "${update_initramfs}" = "no" ]; then
- echo "update-initramfs: Not updating initramfs."
- exit 0
- fi
-
- if [ -z "${version}" ]; then
- set_linked_version
- fi
-
- if [ -z "${version}" ]; then
- set_highest_version
- fi
-
- if [ -z "${version}" ]; then
- set_current_version
- fi
-
- if [ -z "${version}" ]; then
- verbose "Nothing to do, exiting."
- exit 0
- fi
-
- set_initramfs
-
- ro_boot_check
-
- altered_check
-
- backup_initramfs
-
- generate_initramfs
-
- run_bootloader
-
- backup_booted_initramfs
- }
-
- delete()
- {
- if [ -z "${version}" ]; then
- usage "Delete mode requires a version argument"
- fi
-
- set_initramfs
-
- if [ ! -e "${initramfs}" ]; then
- panic "Cannot delete ${initramfs}, doesn't exist."
- fi
-
- if ! version_exists "${version}"; then
- panic "Cannot delete version ${version}: Not created by this utility."
- fi
-
- altered_check
-
- echo "update-initramfs: Deleting ${initramfs}"
-
- delete_sha1
-
- rm -f "${initramfs}"
- }
-
- # Check for update mode on existing and modified initramfs
- altered_check()
- {
- # No check on takeover
- [ "${takeover}" = 1 ] && return 0
- if [ ! -e "${initramfs}" ]; then
- mild_panic "${initramfs} does not exist. Cannot update."
- fi
- if ! compare_sha1; then
- echo "update-initramfs: ${initramfs} has been altered." >&2
- mild_panic "update-initramfs: Cannot update. Override with -t option."
- fi
- }
-
- # Defaults
- verbose=0
- yes=0
- # We default to takeover=1 in Ubuntu, but not Debian
- takeover=1
-
- ##
-
- while getopts "k:cudyvtb:h?" flag; do
- case "${flag}" in
- k)
- version="${OPTARG}"
- ;;
- c)
- mode="c"
- ;;
- d)
- mode="d"
- ;;
- u)
- mode="u"
- ;;
- v)
- verbose="1"
- ;;
- y)
- yes="1"
- ;;
- t)
- takeover="1"
- ;;
- b)
- BOOTDIR="${OPTARG}"
- if [ ! -d "${BOOTDIR}" ]; then
- echo "Error: ${BOOTDIR} is not a directory."
- exit 1
- fi
- ;;
- h|?)
- usage
- ;;
- esac
- done
-
- # Validate arguments
- if [ -z "${mode}" ]; then
- usage "You must specify at least one of -c, -u, or -d."
- fi
-
- if [ "${version}" = "all" ] \
- || ( [ "${update_initramfs}" = "all" ] && [ -z "${version}" ] ); then
- : FIXME check for --yes, and if not ask are you sure
- get_sorted_versions
- if [ -z "${version_list}" ]; then
- verbose "Nothing to do, exiting."
- exit 0
- fi
-
- OPTS="-b ${BOOTDIR}"
- if [ "${verbose}" = "1" ]; then
- OPTS="${OPTS} -v"
- fi
- if [ "${takeover}" = "1" ]; then
- OPTS="${OPTS} -t"
- fi
- if [ "${yes}" = "1" ]; then
- OPTS="${OPTS} -y"
- fi
- for u_version in ${version_list}; do
- # Don't stop if one version doesn't work.
- set +e
- verbose "Execute: ${0} -${mode} -k \"${u_version}\" ${OPTS}"
- "${0}" -${mode} -k "${u_version}" ${OPTS}
- set -e
- done
- exit 0
- fi
-
-
- case "${mode}" in
- c)
- create
- ;;
- d)
- delete
- ;;
- u)
- update
- ;;
- esac
-